package com.mybaits.db;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidPooledConnection;
import com.mybaits.config.DBIdentifier;
import com.mybaits.config.DDSHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;

import java.util.Map;

/**
 * @description: 定义动态数据源派生类。从基础的DataSource派生，动态性自己实现
 * @author: zyj
 * @create: 2019-11-27 16:26
 **/
public class DynamicDataSource extends DruidDataSource {

    Logger logger = LoggerFactory.getLogger(DynamicDataSource.class);

    private String INIT_DATASOURCE = "my-model";

    @Value("${spring.datasource.url}")
    private String url;
    @Value("${spring.datasource.username}")
    private String username;
    @Value("${spring.datasource.password}")
    private String password;
    @Value("${spring.datasource.driver-class-name}")
    private String driverClassName;

    /**
     * 改写本方法是为了在请求不同工程的数据时去连接不同的数据库。
     */
    @Override
    public DruidPooledConnection getConnection(){

        Map<String, String> dataSourceMessage = DBIdentifier.getProjectCode();
        DruidDataSource dataSourceSefault = DDSHolder.instance().getDDS(INIT_DATASOURCE);
        try {
            //初始化数据库
            if(dataSourceMessage==null||dataSourceMessage.isEmpty()){

                if(dataSourceSefault==null){
                    DruidDataSource newDDS = initDDS(dataSourceMessage,true);
                    DDSHolder.instance().addDDS(INIT_DATASOURCE, newDDS);
                    return newDDS.getConnection();
                }

                return DDSHolder.instance().getDDS(INIT_DATASOURCE).getConnection();
            }

            String projectCode = String.valueOf(dataSourceMessage.get("dataCode"));
            //1、获取数据源
            DruidDataSource dds = DDSHolder.instance().getDDS(projectCode);

            //2、如果数据源不存在则创建
            if (dds == null) {
                try {
                    DruidDataSource newDDS = initDDS(dataSourceMessage,false);
                    DDSHolder.instance().addDDS(projectCode, newDDS);
                } catch (IllegalArgumentException | IllegalAccessException e) {
                    logger.error("Init data source fail. projectCode:" + projectCode);
                    return null;
                }
            }

            dds = DDSHolder.instance().getDDS(projectCode);

            return dds.getConnection();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 以当前数据对象作为模板复制一份。
     * b 是否为初始化数据库
     * @return dds
     * @throws IllegalAccessException
     * @throws IllegalArgumentException
     */
    private DruidDataSource initDDS( Map<String, String> valueMap, boolean b) throws IllegalArgumentException, IllegalAccessException {

        DruidDataSource dds = new DruidDataSource();
        dds.setDefaultAutoCommit(false);

        //1、复制PoolConfiguration属性
//        Properties property = new Properties();
//        Field[] pfields = Properties.class.getDeclaredFields();
//        for (Field f : pfields) {
//            f.setAccessible(true);
//            Object value = f.get(this.getProperties());
//            try {
//                f.set(property, value);
//            } catch (Exception e) {
//                //有一些static final的属性不能修改。忽略。
//                logger.info("Set value fail. attr name:" + f.getName());
//                continue;
//            }
//        }
//
//        dds.setConnectProperties(property);


        //2:拼接数据源
        if(b){
            dds.setUrl(url);
            dds.setDriverClassName(driverClassName);
            dds.setUsername(username);
            dds.setPassword(password);
            dds.setMaxActive(25);
            return dds;
        }

        // 3、设置数据库名称和IP(一般来说，端口和用户名、密码都是统一固定的)
        String urlFormat = "jdbc:mysql://%s:%s/%s?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true";
        String url = String.format(urlFormat, valueMap.get("databaseUrl"), valueMap.get("databasePort"), valueMap.get("tenantDatabase"));
        dds.setUrl(url);
        dds.setUsername(valueMap.get("tenantDatabaseName"));
        dds.setPassword(valueMap.get("tenantDatabasePasswd"));
        dds.setDriverClassName(valueMap.get("drivername"));
        dds.setMaxActive(25);

        return dds;
    }

}
